/**
 * 20220304:[require] to [import]...jordia
 */
import {Ray,Vector3} from 'three';
import DragLimit from "./drag-limit";
import Geometry from "../../general/geometry-utils";

const MAX_RAY_LENGTH=1e6;
const R2D=180/Math.PI;
const D2R=Math.PI/180;

/**
 * 沿向量拖动
 * @param values {object}
 * limitAngle:30° 拖动角度小于此值时将锁定不能拖动，避免小角度时突然拖到极远
 * 继承的其它...
 */
export default class DragVectorLimit extends DragLimit{
    constructor(values){
        super(values);
    }

    /**
     * 获取约束类型
     * @returns {string}
     */
    get type(){
        return 'dragVectorLimit';
    }

    /**
     * 获取约束向量
     * @returns {Vector3}
     */
    get vector(){
        return this._vector;
    }

    /**
     * 设置约束向量
     * @param vector
     */
    set vector(vector){
        this._vector.copy(vector);
    }

    /**
     * 获取锁定角度
     * @returns {number}
     */
    get limitAngle(){
        return this._limitAngle*R2D;
    }

    /**
     * 设置锁定角度
     * @param degree
     */
    set limitAngle(degree){
        this._limitAngle=degree*D2R;
    }

    modifyMove(object,v,callback,camera) {
        object.getWorldPosition(this._tempPosition);
        this._tempDir.copy(this._vector);
        this._tempS.copy(this._tempDir).negate().multiplyScalar(MAX_RAY_LENGTH / 2).add(this._tempPosition);
        this._tempE.copy(this._tempDir).multiplyScalar(MAX_RAY_LENGTH / 2).add(this._tempPosition);
        camera.getWorldPosition(this._cameraPosition);
        this._tempDirection.subVectors(v, this._cameraPosition).normalize();
        let tempAngle = this._tempDirection.angleTo(this._tempDir);
        if ((tempAngle < this._limitAngle) || (tempAngle > Math.PI - this._limitAngle))return;
        this._tempRay.set(this._cameraPosition, this._tempDirection);
        let closestPoint=new Vector3();
        Geometry.distanceSqOfRayAndSpline(this._tempRay,[this._tempS,this._tempE],null,closestPoint);
        this._transformVector(object,closestPoint);
        object.position.copy(closestPoint);
        callback(object,closestPoint);
    }
    dispose(){
        super.dispose();
        this._limitAngle=null;

        this._vector=null;
        this._tempPosition=null;
        this._tempS=null;
        this._tempE=null;
        this._cameraPosition=null;
        this._tempDirection=null;
        this._tempDir=null;
        this._tempRay=null;
    }

    _initVariable() {
        super._initVariable();
        this._limitAngle=this._values.limitAngle||30*D2R;

        this._vector=new Vector3(0,1,0);
        this._tempPosition=new Vector3();
        this._tempS=new Vector3();
        this._tempE=new Vector3();
        this._cameraPosition=new Vector3();
        this._tempDirection=new Vector3();
        this._tempDir=new Vector3();
        this._tempRay=new Ray();
    }
}